#include <libraries/kio.h>

/*				 STRUCTURE OF LINKED LIST DESCRIBING GDT USAGE			*/
/*												*
*     GDT ENTRY NUMBER		|	USE							*
*=======================================================					*
* Number from the above funct-	|	KERNCS = Kernel CS Code Segment				*
* ion (encodeGdtEntry)				|	KERNDS = Kernel DS Data Segment				*
*											|	KERNTSS = Kernel TSS Descriptor				*
*												KERNNULL = Null Descriptor						*
*												LDT<pid num><function (CS/DS/TSS) = LDT Descriptor for a local proccess		*
*												*
*/

/* This structure is the actuall structure used for the GDT. The GDTbookeeping structure allows for system book keeping */

struct GDTentry_struct {
	int number;
	char function;	
	unsigned short int base_low;
	unsigned short int limit_low;
	unsigned short int base_middle;
	unsigned char access;
	unsigned char granularity;
}__attribute__((__packed__)); /*check to see that this is the right syntax for the attribute */
/* This is the structure that is actually used to access GDTentry. GDTentry_struct is a prototype */
struct GDTentry_struct gdt[8192];


/* This GDTbookeeping structure allows for the system to see what is actually IN the GDT */

struct GDTbookeeping_struct { /*Prototype structure */
	int number;
	char use; /* See above for the possible values of this field */
	unsigned long base, limit;
	unsigned short int ringlevel; /* What protection ring is the entry allocated to? */
} 
struct GDTbookeeping_struct GDTbookeeping[8192];
	



/* GDT ENTRY SCHEME */
/*============================================================================================================* 
*	|Limit 0:7|Limit 8:15| Base 0:7 | Base 7:15 | Base 16:23 | Access Byte | Flags | Limit 16:19 | Base 24:31| *
*=============================================================================================================*
*/
/* Setup a descriptor in the Global Descriptor Table */
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran){
    /* Setup the descriptor base address */
    gdt[num].base_low = (base & 0xFFFF);
    gdt[num].base_middle = (base >> 16) & 0xFF;
    gdt[num].base_high = (base >> 24) & 0xFF;

    /* Setup the descriptor limits */
    gdt[num].limit_low = (limit & 0xFFFF);
    gdt[num].granularity = ((limit >> 16) & 0x0F);

    /* Finally, set up the granularity and access flags */
    gdt[num].granularity |= (gran & 0xF0);
    gdt[num].access = access;
    
    /* Add to the bookeeping structure */
    
    GDTbookeeping[num].number = num;
    strcpy(GDTbookeeping[num].use, use);
    GDTbookeeping[num].base = base;
    GDTbookeeping[num].limit = limit;
    strcpy(GDTbookeeping[num].ringlevel, access[4]);
    
}

/* This will be a function in start.asm. We use this to properly
*  reload the new segment registers */
extern void gdt_flush();












